﻿using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Core.Caching;
using Core.Helpers;
using Core.Identity.Common.Interfaces.Common.Interfaces;
using Core.Identity.Roles.Caching;
using Core.Models;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Core.Identity.Roles.Features.Commands.Update;

/// <summary>
/// 修改角色
/// </summary>
public class UpdateRoleCommand : ICacheInvalidatorRequest<Result<bool>>
{
    /// <summary>
    /// 角色唯一标识
    /// </summary>
    public Guid Id { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    [Required(ErrorMessage = "编码必传")]
    public required string Code { get; set; }
    /// <summary>
    /// 角色名
    /// </summary>
    [Required(ErrorMessage = "角色名必传")]
    public required string Name { get; set; }
    /// <summary>
    /// 设置排序
    /// </summary>
    public int? Sort { get; set; }
    /// <summary>
    /// 设置描述
    /// </summary>
    public string? Description { get; set; }
    /// <summary>
    /// 设置启用/禁用
    /// </summary>
    public bool Enabled { get; set; }

    [JsonIgnore]
    public IEnumerable<string>? Tags => RolesCacheKey.Tags;
}

public class UpdateRoleCommandHandler(IIdentityDbContext dbContext) : IRequestHandler<UpdateRoleCommand, Result<bool>>
{

    public async Task<Result<bool>> Handle(UpdateRoleCommand request, CancellationToken cancellationToken)
    {
        var role = await dbContext.Roles
            .FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken);
        ExceptionHelper.ThrowIfNull(role, "数据不存在");

        if (role!.Code != request.Code)
        {
            role = await dbContext.Roles
                .FirstOrDefaultAsync(x => x.Code == request.Code && x.Id != request.Id, cancellationToken);
            ExceptionHelper.ThrowIfNotNull(role, "编号已被占用");
            role!.Recode(request.Code);
        }
        role.Rename(request.Name);
        role.Sort = request.Sort;
        role.ChangeDescription(request.Description);
        role.SetEnabled(request.Enabled);

        dbContext.Roles.Update(role);

        var result = await dbContext.SaveChangesAsync(cancellationToken) > 0;
        return await Result<bool>.SucceedAsync(result, result, ["修改失败"]);
    }
}
